package com.grandtech.insurance.service.impl;


import com.grandtech.insurance.cache.CacheLayerScheme;
import com.grandtech.insurance.common.bean.SqlVo;
import com.grandtech.insurance.common.db.jdbc.pg.Feature2SqlUtil;
import com.grandtech.insurance.common.db.jdbc.pg.PGTBStructureUtil;
import com.grandtech.insurance.dao.app.FeatureDao;
import com.grandtech.insurance.domain.BoundModel;
import com.grandtech.insurance.service.app.IFeatureService;
import com.mapbox.geojson.Feature;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Service
@Transactional
public class FeatureServiceImpl implements IFeatureService {

    Log log = LogFactory.getLog(IFeatureService.class);

    @Autowired
    private FeatureDao featureDao;


    @Override
    public Map getLayerScheme(String tableName) {
        Map _map = CacheLayerScheme.getInstance().getTableSchemeByName(tableName);
        if (_map == null) {
            List<Map> list = featureDao.getLayerSchemeInfo(tableName);
            _map = PGTBStructureUtil.readTableStructure(tableName, list);
            CacheLayerScheme.getInstance().cacheTableSchemeByName(tableName, _map);
        }
        return _map;
    }

    @Override
    public Map get(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByFeature(tableStructure, feature);
        log.debug("get：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return map;
    }

    @Override
    public Feature getFeature(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByFeature(tableStructure, feature);
        log.debug("getFeature：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public Feature getFeature1(String tableName, Map map) {
        Map tableStructure = this.getLayerScheme(tableName);
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public Feature get(String tableName, Object pk) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2Sql(tableStructure, pk);
        log.debug("get：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public Feature getFeature(String tableName, Feature feature, String... fields) {
        Map condition = Feature2SqlUtil.featureFields2Map(feature, fields);
        return this.getFeatureByMapCondition(tableName, condition);
    }

    @Override
    public Feature getFeatureByMapCondition(String tableName, Map condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByMap(tableStructure, condition);
        log.debug("getFeatureByMapCondition：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public Feature getFeatureByCondition(String tableName, String condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition);
        log.debug("getFeatureByCondition：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public List<Feature> getList(String tableName, String condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition);
        log.debug("getList：" + sql);
        List<Map> list = featureDao.getList(new SqlVo(sql));
        return Feature2SqlUtil.map2ListFeature(tableStructure, list);
    }

    @Override
    public List<Feature> getList(String tableName, String condition, String shapeFun) {
        return null;
    }

    @Override
    public Boolean insert(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        //生成insert的sql语句，并运行
        String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
        Map tableInfo = (Map) tableStructure.get("tableInfo");
        sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
        //Long id = featureDao.insert(new SqlVo(sql));
        //if (id > 0) return true;
        return false;
    }

    @Override
    public Feature insertF(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        //生成insert的sql语句，并运行
        String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
        Map tableInfo = (Map) tableStructure.get("tableInfo");
        sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
        log.debug("insertF：" + sql);
        Long id = featureDao.insert(new SqlVo(sql));
        //从数据库中取出插入的结果
        //Long id = Long.valueOf("666");
        String selectFeatureSql = Feature2SqlUtil.spatialMap2Sql(tableStructure, id);
        Map featureMap = featureDao.get(new SqlVo(selectFeatureSql));
        Feature serviceFeature = Feature2SqlUtil.map2Feature(tableStructure, featureMap);
        return serviceFeature;
    }

    @Override
    public Boolean insertOrUpdate(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        boolean isExist = isExistFeature(tableName, feature);
        if (isExist) {
            String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature);
            log.debug("insertOrUpdate：" + sql);
            Integer flag = featureDao.update(new SqlVo(sql));
            return flag.intValue() == 0 ? false : true;
        } else {
            //生成insert的sql语句，并运行
            String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("insertOrUpdate：" + sql);
            featureDao.insert(new SqlVo(sql));
            return true;
        }
    }

    @Override
    public Boolean insertOrUpdate(String tableName, Feature feature, String... fields) {
        Map condition = Feature2SqlUtil.featureFields2Map(feature, fields);
        return this.insertOrUpdate(tableName, feature, condition);
    }

    @Override
    public Boolean insertOrUpdate(String tableName, Feature feature, Map condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        boolean isExist = isExistFeature(tableName, feature, condition);
        if (isExist) {
            String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature, condition);
            log.debug("insertOrUpdate：" + sql);
            Integer flag = featureDao.update(new SqlVo(sql));
            return flag.intValue() == 0 ? false : true;
        } else {
            //生成insert的sql语句，并运行
            String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("insertOrUpdate：" + sql);
            featureDao.insert(new SqlVo(sql));
            return true;
        }
    }

    @Override
    public Boolean insertOrUpdate(String tableName, Feature feature, String condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        boolean isExist = isExistFeature(tableName, feature, condition);
        if (isExist) {
            String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature, condition);
            log.debug("insertOrUpdate：" + sql);
            Integer flag = featureDao.update(new SqlVo(sql));
            return flag.intValue() == 0 ? false : true;
        } else {
            //生成insert的sql语句，并运行
            String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("insertOrUpdate：" + sql);
            featureDao.insert(new SqlVo(sql));
            return true;
        }
    }

    @Override
    public Boolean isExistFeature(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        if(!feature.hasProperty("objectid")){
            return false;
        }
        Integer integer = feature.getNumberProperty("objectid").intValue();
        String sql = Feature2SqlUtil.spatialMap2Sql(tableStructure, integer);
        log.debug("isExistFeature：" + sql);
        List<Map> features = featureDao.getList(new SqlVo(sql));
        return (features == null || features.size() == 0) ? false : true;
    }

    @Override
    public Boolean isExistFeature(String tableName, Feature feature, String... fields) {
        Map condition = Feature2SqlUtil.featureFields2Map(feature, fields);
        return this.isExistFeature(tableName, feature, condition);
    }

    @Override
    public Boolean isExistFeature(String tableName, Feature feature, Map condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByMap(tableStructure, condition);
        log.debug("isExistFeature：" + sql);
        List<Map> features = featureDao.getList(new SqlVo(sql));
        return (features == null || features.size() == 0) ? false : true;
    }

    @Override
    public Boolean isExistFeature(String tableName, Feature feature, String condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition);
        log.debug("isExistFeature：" + sql);
        List<Map> features = featureDao.getList(new SqlVo(sql));
        return (features == null || features.size() == 0) ? false : true;
    }

    @Override
    public Boolean update(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature);
        log.debug("update：" + sql);
        Integer flag = featureDao.update(new SqlVo(sql));
        if (flag == null || flag.intValue() == 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Boolean update(String tableName, Feature feature, String... fields) {
        Map condition = Feature2SqlUtil.featureFields2Map(feature, fields);
        return this.update(tableName, feature, condition);
    }

    @Override
    public Boolean update(String tableName, Feature feature, Map condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature, condition);
        log.debug("update：" + sql);
        Integer flag = featureDao.update(new SqlVo(sql));
        if (flag == null || flag.intValue() == 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Boolean delete(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialFeature2DelSql(tableStructure, feature);
        log.debug("delete：" + sql);
        int res = featureDao.delete(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public Boolean delete(String tableName, Feature feature, String... fields) {
        Map condition = Feature2SqlUtil.featureFields2Map(feature, fields);
        return this.delete(tableName, condition);
    }

    @Override
    public Boolean delete(String tableName, Map condition) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialFeature2DelSql(tableStructure, condition);
        log.debug("delete：" + sql);
        int res = featureDao.delete(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public void exeSql(String sql) {
        featureDao.exeSql(new SqlVo(sql));
    }

    //==============================邪恶的分割线======================================

    @Override
    public Map get(Map tableStructure, Feature feature) {
        String sql = "";
        log.debug("get：" + sql);
        return featureDao.get(new SqlVo(sql));
    }

    @Override
    public Feature get(Map tableStructure, Object pk) {
        String sql = Feature2SqlUtil.spatialMap2Sql(tableStructure, pk);
        log.debug("get：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    /**
     * @param tableStructure
     * @param condition
     * @return
     */
    @Override
    public Feature getFeatureByMapCondition(Map tableStructure, Map condition) {
        String sql = Feature2SqlUtil.spatialMap2SqlByMap(tableStructure, condition);
        log.debug("getFeatureByMapCondition：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public Feature getFeatureByCondition(Map tableStructure, String condition) {
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition);
        log.debug("getFeatureByCondition：" + sql);
        Map map = featureDao.get(new SqlVo(sql));
        return Feature2SqlUtil.map2Feature(tableStructure, map);
    }

    @Override
    public List<Feature> getList(Map tableStructure, String condition) {
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition);
        log.debug("getList：" + sql);
        List<Map> list = featureDao.getList(new SqlVo(sql));
        return Feature2SqlUtil.map2ListFeature(tableStructure, list);
    }

    @Override
    public List<Feature> getList(String tableName, List<Feature> features, String... fields) {
        Map tableStructure = this.getLayerScheme(tableName);
        String sql = Feature2SqlUtil.spatialMap2SqlByField(tableStructure, features, fields);
        log.debug("getList：" + sql);
        List<Map> list = featureDao.getList(new SqlVo(sql));
        return Feature2SqlUtil.map2ListFeature(tableStructure, list);
    }

    public List<Feature> getList(Map tableStructure, String condition, boolean p2p) {
        String sql = Feature2SqlUtil.spatialMap2SqlByWhere(tableStructure, condition, p2p);
        log.debug("getList：" + sql);
        List<Map> list = featureDao.getList(new SqlVo(sql));
        return Feature2SqlUtil.map2ListFeature(tableStructure, list);
    }

    @Override
    public Map<Map, Feature> batchInsertF(Map<Map, Feature> featureMap) {
        if (featureMap == null) return null;
        for (Map tableStructure : featureMap.keySet()) {
            Feature feature = featureMap.get(tableStructure);
            //生成insert的sql语句，并运行
            String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("batchInsertF：" + sql);
            //Long id = featureDao.insert(new SqlVo(sql));
            Long id = Long.valueOf("666");
            //从数据库中取出插入的结果
            String selectFeatureSql = Feature2SqlUtil.spatialMap2Sql(tableStructure, id);
            Map _featureMap = featureDao.get(new SqlVo(selectFeatureSql));
            Feature serviceFeature = Feature2SqlUtil.map2Feature(tableStructure, _featureMap);
            featureMap.put(tableStructure, serviceFeature);
        }
        return featureMap;
    }

    @Override
    public Feature insertF(Map tableStructure, Feature feature) {
        //生成insert的sql语句，并运行
        String sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
        Map tableInfo = (Map) tableStructure.get("tableInfo");
        sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
        log.debug("insertF：" + sql);
        //Long id = featureDao.insert(new SqlVo(sql));
        Long id = Long.valueOf("666");
        //从数据库中取出插入的结果
        String selectFeatureSql = Feature2SqlUtil.spatialMap2Sql(tableStructure, id);
        Map featureMap = featureDao.get(new SqlVo(selectFeatureSql));
        Feature serviceFeature = Feature2SqlUtil.map2Feature(tableStructure, featureMap);
        return serviceFeature;
    }

    @Override
    public Boolean update(Map tableStructure, Feature feature) {
        String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature);
        log.debug("update：" + sql);
        int res = featureDao.update(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public Boolean update(Map tableStructure, Feature feature, Map condition) {
        String sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature, condition);
        log.debug("update：" + sql);
        int res = featureDao.update(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public Boolean delete(Map tableStructure, Feature feature) {
        String sql = Feature2SqlUtil.spatialFeature2DelSql(tableStructure, feature);
        log.debug("delete：" + sql);
        int res = featureDao.delete(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public Boolean delete(Map tableStructure, Feature feature, Map condition) {
        String sql = Feature2SqlUtil.spatialFeature2DelSql(tableStructure, condition);
        log.debug("delete：" + sql);
        int res = featureDao.delete(new SqlVo(sql));
        return res == 0 ? false : true;
    }

    @Override
    public Map getGraffitiByObjectid(Integer objectid) {
        return featureDao.getGraffitiByObjectid(objectid);
    }

    @Override
    public Map getGraffitiByObjectid1(Integer objectid) {
        return featureDao.getGraffitiByObjectid1(objectid);
    }

    @Override
    public Map pt1(Integer objectid) {
        return featureDao.pt1(objectid);
    }

    @Override
    public Map pt2(Integer objectid) {
        return featureDao.pt2(objectid);
    }

    @Override
    public List<BoundModel> getBounds(Integer objectid) {
        return featureDao.getBounds(objectid);
    }

    @Override
    public Feature insertOrUpdateF(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        final String[] MULTI_PK = new String[]{"objectid"};
        Map condition = Feature2SqlUtil.featureFields2Map(feature, MULTI_PK);
        String sql = Feature2SqlUtil.spatialMap2SqlByMap(tableStructure, condition);
        List<Map> features2 = featureDao.getList(new SqlVo(sql));
        boolean isExist =  (features2 == null || features2.size() == 0) ? false : true;
        if (isExist) {
            sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature,condition);
            log.debug("insertOrUpdate：" + sql);
            Integer flag = featureDao.update(new SqlVo(sql));
            return feature;
        } else {
            //生成insert的sql语句，并运行
            sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("insertOrUpdate：" + sql);
            Long id = featureDao.insert(new SqlVo(sql));
            //从数据库中取出插入的结果
            String selectFeatureSql = Feature2SqlUtil.spatialMap2Sql(tableStructure, id);
            Map featureMap = featureDao.get(new SqlVo(selectFeatureSql));
            Feature serviceFeature = Feature2SqlUtil.map2Feature(tableStructure, featureMap);
            return serviceFeature;
        }
    }

    @Override
    public Feature insertOrUpdateF1(String tableName, Feature feature) {
        Map tableStructure = this.getLayerScheme(tableName);
        final String[] MULTI_PK = new String[]{"id"};
        Map condition = Feature2SqlUtil.featureFields2Map(feature, MULTI_PK);
        String sql = Feature2SqlUtil.spatialMap2SqlByMap(tableStructure, condition);
        List<Map> features2 = featureDao.getList(new SqlVo(sql));
        boolean isExist =  (features2 == null || features2.size() == 0) ? false : true;
        if (isExist) {
            sql = Feature2SqlUtil.spatialFeature2UpdateSql(tableStructure, feature,condition);
            log.debug("insertOrUpdate：" + sql);
            Integer flag = featureDao.update(new SqlVo(sql));
            return feature;
        } else {
            //生成insert的sql语句，并运行
            sql = Feature2SqlUtil.spatialFeature2InsertSql(tableStructure, feature);
            Map tableInfo = (Map) tableStructure.get("tableInfo");
            sql = sql + " RETURNING " + tableInfo.get("pkName").toString();
            log.debug("insertOrUpdate：" + sql);
            Long id = featureDao.insert(new SqlVo(sql));
            //从数据库中取出插入的结果
            String selectFeatureSql = Feature2SqlUtil.spatialMap2Sql(tableStructure, id);
            Map featureMap = featureDao.get(new SqlVo(selectFeatureSql));
            Feature serviceFeature = Feature2SqlUtil.map2Feature(tableStructure, featureMap);
            return serviceFeature;
        }
    }
}
